package channelScheduler

import (
	"gitee.com/fierce_wolf/go-fox-edge-channel-common/channelAPI"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEntityManager"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEnv"
	"gitee.com/fierce_wolf/go-fox-edge-common/commRedisRpc"
	"time"
)

type channelRespondScheduler struct {
}

// Scheduler 创建一个线程
func (e *channelRespondScheduler) Scheduler() {
	go e.scheduler()
}

// 线程函数
func (e *channelRespondScheduler) scheduler() {
	for true {
		if !commEntityManager.EntityManager.Initialized {
			time.Sleep(1 * time.Second)
			continue
		}

		requestVO, err := commRedisRpc.Channel.Server.Request.Pop(commEnv.Service.ModelName, 1*time.Second)
		if err != nil || requestVO == nil {
			continue
		}

		// 处理数据
		e.updateDeviceRespond(requestVO)
	}
}

func (e *channelRespondScheduler) updateDeviceRespond(requestVO *commRedisRpc.ChannelRequestVO) {
	if "exchange" == requestVO.Mode {
		// 一问一答模式
		respondVO := e.execute(requestVO)

		// 将UUID回填回去
		respondVO.Uuid = requestVO.Uuid
		respondVO.Type = commEnv.Service.ModelName

		// 返回数据
		commRedisRpc.Channel.Server.Respond.Push(respondVO.Type, requestVO.Uuid, respondVO)
	} else if "publish" == requestVO.Mode {
		// 一问一答模式
		respondVO := e.publish(requestVO)

		// 将UUID回填回去
		respondVO.Uuid = requestVO.Uuid
		respondVO.Type = commEnv.Service.ModelName

		// 返回数据
		commRedisRpc.Channel.Server.Respond.Push(respondVO.Type, requestVO.Uuid, respondVO)
	}
}

func (e *channelRespondScheduler) execute(requestVO *commRedisRpc.ChannelRequestVO) (respondVO *commRedisRpc.ChannelRespondVO) {
	if requestVO.Timeout > 60*1000 {
		return commRedisRpc.Type.ChannelRespondVO.Error(requestVO, "为了避免设备没响应时造成堵塞，不允许最大超时大于1分钟!")
	}

	// 调用接口
	respondVO, err := channelAPI.Service.Execute(requestVO)
	if err != nil {
		return commRedisRpc.Type.ChannelRespondVO.Error(requestVO, err.Error())
	}
	if respondVO == nil {
		return commRedisRpc.Type.ChannelRespondVO.Error(requestVO, "空指针异常")
	}

	return respondVO
}

func (e *channelRespondScheduler) publish(requestVO *commRedisRpc.ChannelRequestVO) (respondVO *commRedisRpc.ChannelRespondVO) {
	err := channelAPI.Service.Publish(requestVO)
	if err != nil {
		return commRedisRpc.Type.ChannelRespondVO.Error(requestVO, err.Error())
	}

	respondVO = commRedisRpc.Type.ChannelRespondVO.Ok(requestVO)
	respondVO.Recv = nil
	return respondVO
}
